#include "SocketIO.h"
#include <iostream>
#include <string.h>
SocketWriter::SocketWriter(socketinf si) {
    this->si = si;
}
bool SocketWriter::sendFrame(unsigned char flag, unsigned long long payloadLen)  {
    this->surplus = payloadLen;
    return this->dataframe.sendFrame(this->si.socket_fd, flag, payloadLen);
}

void SocketWriter::write(const char * buf, size_t len)  {
    int cnt = 0, target = len;
    while ( target > 0 ) {
        cnt = send(this->si.socket_fd, buf, len, 0);
        if( cnt == -1){
            throw SocketException("Socket send return -1");
        }
        target -= cnt;
    }
    this->surplus -= len;
}

void SocketWriter::writeOne(const char * buf, unsigned long long len)  {
    if (this->surplus != 0) {
        throw SocketException("Frame payload data not finished read");
    }
    this->sendFrame(0, len);
    this->write(buf, len);

}
void SocketWriter::setTimeout(unsigned int sec) {
    #ifdef __MINGW32__
    int tv = sec*1000;
    if (setsockopt(this->si.socket_fd, SOL_SOCKET, SO_SNDTIMEO, (const char *)&tv, sizeof(tv)) == -1)
        throw SocketException(strerror(errno));
    #else
    struct timeval tv;
    tv.tv_sec = sec;
    tv.tv_usec = 0;
    if (setsockopt(this->si.socket_fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) == -1)
        throw SocketException(strerror(errno));
    #endif
}

SocketIO::SocketIO(socketinf si) {
    this->si = si;
    this->socketReader = new SocketReader(si);
    this->socketWriter = new SocketWriter(si);
}
SocketIO::SocketIO(socketinf si, unsigned int sec)  {
    this->si = si;
    this->socketReader = new SocketReader(si);
    this->socketWriter = new SocketWriter(si);
    this->socketReader->setTimeout(sec);
    this->socketWriter->setTimeout(sec);
}
SocketIO::~SocketIO() {
    delete this->socketReader;
    delete this->socketWriter;
}
SOCKET_T SocketIO::getSocketFD() {
    return this->si.socket_fd;
}
void SocketIO::close() {
    this->si.close();
}
SocketReader::~SocketReader() {
}

SocketReader::SocketReader(socketinf si) {
    this->si = si;
    this->payloadLength = 0;
}

void SocketReader::setTimeout(unsigned int sec) {
    #ifdef __MINGW32__
    int tv = sec*1000;
    if (setsockopt(this->si.socket_fd, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv, sizeof(tv)) == -1)
        throw SocketException(strerror(errno));
    #else
    struct timeval tv;
    tv.tv_sec = sec;
    tv.tv_usec = 0;
    if (setsockopt(this->si.socket_fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1)
        throw SocketException(strerror(errno));
    #endif
}

int SocketReader::readFrame() {
    dataFrame.readFrame(this->si.socket_fd);
    this->payloadLength = dataFrame.length;
    return this->dataFrame.flag;
}

unsigned char SocketReader::getFrameFlag() {
    return this->dataFrame.flag;
}

unsigned long long SocketReader::getFrameLength() {
    return this->dataFrame.length;
}

int SocketReader::read(char * buf, size_t max_len)  {
    // 负载长度判断
    if (this->payloadLength == 0) {
        return -1;
    }
    ssize_t cnt = 0;
    int willRead = this->payloadLength < max_len ? this->payloadLength : max_len;
    cnt = recv(this->si.socket_fd, buf, willRead, MSG_WAITALL);
    if (cnt <= 0) {
        throw SocketException(strerror(errno));
    }
    this->payloadLength -= cnt;
    return cnt;
}

void SocketReader::resetPayloadLen(unsigned long long len) {
    this->payloadLength = len;
    this->dataFrame.length = len;
}

int SocketReader::readOne(char * buf, size_t max_len) {
    if (this->payloadLength != 0) {
        throw SocketException("Frame payload data not finished read");
    }

    this->readFrame();
    int cnt = this->read(buf, max_len);
    if (cnt != (int)this->dataFrame.length) {
        throw SocketException("readOne: Not enough buffer length");
    }
    return cnt;
}